package PlPN::Sink;
use strict;

our $AUTOLOAD;

sub new {
	my $class = shift;
	my $self = bless {}, $class;
	return $self;
}

sub register {
	my ($self, $event, $subref) = @_;
	
	$self->{$event} ||= [];
	for my $check (@{ $self->{$event} }) {
		next unless $check == $subref;
		warn "Subref $subref already registered for event $event";
		return;
	}
	push @{ $self->{$event} }, $subref;
}

sub unregister {
	my ($self, $event, $subref) = @_;
	
	if ($self->{$event}) {
		for my $i (0..$#{ $self->{$event} }) {
			next unless $self->{$event}[$i] == $subref;
			splice (@{ $self->{$event} }, $i, 1);
			return;
		}
	}
	warn "Subref $subref not registered for event $event";
	return;
}

sub call {
	my $self = shift;
	my $event = shift;
	return unless $self->{$event};
	
	for my $subref (@{ $self->{$event} }) {
		$subref->(@_);
	}
}

package PlPN::AppSink;
use strict;

our @ISA = qw(PlPN::Sink PlPN::AppEventSink);

sub OnNewDocument {
	my ($self, $doc) = @_;
	
	$doc->AddEventSink($PlPN::DocSink);
	$doc->AddEventSink($PlPN::EditorSink);
	
	$self->call('OnNewDocument', $doc);
}

sub OnAppClose {
	my $self = shift;
	
	# clear out the DataFreezer so it doesn't persist between sessions
	PlPN::PN()->GetOptionsManager->Set('PlPN', 'DataFreezer', '');
	
	$self->call('OnAppClose', @_);
}

sub OnDocSelected {
	my $self = shift;	
	$self->call('OnDocSelected', @_);
}

sub OnFirstEditorCreated {
	my $self = shift;	
	$self->call('OnFirstEditorCreated', @_);
}

package PlPN::DocSink;
use strict;

our @ISA = qw(PlPN::Sink PlPN::DocumentEventSink);

sub OnSchemeChange {
	my $self = shift;	
	$self->call('OnSchemeChange', @_);
}

sub OnDocClosing {
	my ($self, $doc) = @_;
	
	$self->call('OnDocClosing', $doc);
	
	$doc->RemoveEventSink($PlPN::DocSink);
	$doc->RemoveEventSink($PlPN::EditorSink);
}

sub OnAfterLoad {
	my $self = shift;	
	$self->call('OnAfterLoad', @_);
}

sub OnBeforeSave {
	my $self = shift;	
	$self->call('OnBeforeSave', @_);
}

sub OnAfterSave {
	my $self = shift;	
	$self->call('OnAfterSave', @_);
}

sub OnModifiedChanged {
	my $self = shift;	
	$self->call('OnModifiedChanged', @_);
}

sub OnWriteProtectChanged {
	my $self = shift;	
	$self->call('OnWriteProtectChanged', @_);
}

package PlPN::EditorSink;
use strict;

our @ISA = qw(PlPN::Sink PlPN::TextEditorEventSink);

sub OnCharAdded {
	my $self = shift;	
	$self->call('OnCharAdded', @_);
}


1;
